package zpe.controledeacesso.service;


import java.util.ArrayList;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import zpe.controledeacesso.model.bean.Modulo;
import zpe.controledeacesso.model.bean.Transacao;
import zpe.genericcrud.service.GenericService;

@Service
public class TransacaoService extends GenericService<Transacao> {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private @Autowired ModuloService moduloService;
	
	/**
	 * Atualiza uma transação e conserva os módulos da transação que não pertencem ao usuário.
	 * @param obj
	 * @param mods Módulos do usuário anteriores a que estava associada a transação.
	 * @return
	 *//*
	@Transactional( propagation = Propagation.REQUIRED, rollbackFor = {RuntimeException.class, Exception.class} )
	public Transacao update(Transacao obj) {
		
		List<Modulo> listModulos = new ArrayList<Modulo>();

		Transacao t = findByPrimaryKey( Transacao.class, obj.getId() );
		
		//Pega os módulos de permissão do usuário logado
		for( GrupoDeUsuario m : UsuarioUtil.getUsuarioLogado().getGrupos() ){
			if(!listModulos.contains(m.getModulo()))
				listModulos.add(m.getModulo());
		}
		//Lista com todos os módulos que devem ser asssociados às transações, independente de ser visível ao usuário, para evitar que sejam removidos outros módulos 
		List<Modulo> modsSave = new ArrayList<Modulo>();
		//Adiciona os módulos a serem associados às transações 
		modsSave.addAll( obj.getModulos() );
		
		for( Modulo m : t.getModulos() ){
			boolean naoEsta = true;
			for( Modulo mFiltrado : listModulos ){//Verifica os módulos que não pertencem ao usuário, mas pertencem à transação.
				if( mFiltrado.getId().equals( m.getId() ) ){
					naoEsta = false;
					break;
				}
			}
			//Módulo não visível para o usuário não está associado à transação.
			if( naoEsta ){//Adiciona o módulo
				modsSave.add( m );
			}
		}
		//Configura os módulos da transação.
		obj.setModulos( modsSave );
		return (Transacao)getDao().getEntityManager().merge(obj);
	}	*/
	
	public List<Modulo> findModulos(){
		return moduloService.findAll(Modulo.class, "descricao");
	}
	
	/**
	 * Consulta todas as transações de determinado módulo.
	 * @param idModulo
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<Transacao> findByModulo(int idModulo){
		
		DetachedCriteria c = DetachedCriteria.forClass(Transacao.class);
		c.createAlias("modulos", "mod").add(Restrictions.eq("mod.id", idModulo));
		
		List<Transacao> lista = getDao().getEntityManager().findByCriteria(c);
		
		if(!lista.isEmpty())
			return lista;
		return null;
		
	}
	
	@SuppressWarnings("unchecked")
	public List<Transacao> findByFilter( Transacao transacao ) {
		List<Transacao> lista = new ArrayList<Transacao>();
		DetachedCriteria dc = DetachedCriteria.forClass( Transacao.class );
		if( transacao.getDescricao() != null ){
			dc.add( Restrictions.ilike("descricao", transacao.getDescricao(), MatchMode.ANYWHERE ) );
		}
		if( transacao.getModulo() != null && transacao.getModulo().getId() != null ){
			dc.createAlias( "modulos", "mod" );
			dc.add( Restrictions.eq( "mod.id", transacao.getModulo().getId() ) );
		}
		dc.setResultTransformer( DetachedCriteria.DISTINCT_ROOT_ENTITY );
		dc.addOrder( Order.asc( "descricao" ) );
		lista = getDao().getEntityManager().findByCriteria( dc );
		return lista;
	}

	public boolean findTransacaoExistente(String descricao) {
		DetachedCriteria dc = DetachedCriteria.forClass(Transacao.class);
		dc.add(Restrictions.eq("descricao", descricao));
		
		return !getDao().getEntityManager().findByCriteria(dc).isEmpty();
	}

	public boolean findTransacaoExistente(Transacao entity) {
		DetachedCriteria dc = DetachedCriteria.forClass(Transacao.class);
		dc.add(Restrictions.eq("descricao", entity.getDescricao()));
		dc.add(Restrictions.not(Restrictions.eq("id", entity.getId())));
		
		return !getDao().getEntityManager().findByCriteria(dc).isEmpty();
	}
}